#include "main.h"
// #include "TM4C123.h"
unsigned long int millis = 0;

void init_sysclk()
{
    // 80MHz
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_16MHZ);

    SysTickPeriodSet(tick_peroid);
    SysTickIntRegister(systick_int);
    SysTickEnable();
}

unsigned int hal_get_ms()
{
    return millis;
}

void init_core()
{
    public_a_fun_link_n("led", led_rgb, 3);
    // public_a_var_ref("cc", &c1, 'D');
    public_a_fun_link_n("seta", seta, 1);
    public_a_cmd_link("reg", cmd_reg_set);
    //    public_a_timer(encoder_do_count, 1); //1kHz
    // addTask_(encoder_do_count);
    public_a_timer(task_rx_fifo_monitor, Hz(100));
    // public_a_fun_link_n("dma",test_dma,0);
}

void exp_test_hit();
int main(void)
{
	SystemInit();
    init_sysclk();
    init_pwm(1000, 0);

    init_uart0();

    init_encoder_int();

    lily_millis = hal_get_ms;
    lily_out = sends;
    lily_init();

    init_core();

    init_flash();
    // init_adc();
    // init_timer();
    // exp_test_hit();
    addTaskArg(lily_do,"flash d 3");
	led_rgb(0.5,0,0.2);
    run_tasks();
    return 0;
}

void led_rgb(float r, float g, float b)
{
    // if r = 0, the result is not right
    int pp = PWMGenPeriodGet(PWM1_BASE, PWM_GEN_3) - 2;
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7, pp * g);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6, pp * b);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5, pp * r);
}

void systick_int()
{
    millis++;
    lily_tick();
}

float millisf()
{
    int c = SysTickPeriodGet();
    float ms = (tick_peroid - c);
    return millis + ms / tick_peroid;
}
// freq: Hz
// duty: 0-100
void init_pwm(float freq, float duty)
{
    /*

M1PWM3 PA7/PE5          Motion Control Module 1 PWM 3. This signal is controlled by Module 1 PWM Generator 1
M1PWM4 28 PF0 (5) O TTL Motion Control Module 1 PWM 4. This signal is controlled by Module 1 PWM Generator 2.
M1PWM5 29 PF1 (5) O TTL	Motion Control Module 1 PWM 5. This signal is controlled by Module 1 PWM Generator 2.
M1PWM6 30 PF2 (5) O TTL	Motion Control Module 1 PWM 6. This signal is controlled by Module 1 PWM Generator 3.	
M1PWM7 31 PF3 (5) O TTL Motion Control Module 1 PWM 7. This signal is controlled by Module 1 PWM Generator 3.
    */
    SysCtlPWMClockSet(SYSCTL_PWMDIV_4); // 80M /4 = 20MHz
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
    //配置引脚为PWM功能
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    // unlock PortF F0
    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;
    HWREG(GPIO_PORTF_BASE + GPIO_O_AFSEL) |= 0x01;

    GPIOPinConfigure(GPIO_PF3_M1PWM7);
    GPIOPinConfigure(GPIO_PF2_M1PWM6);
    GPIOPinConfigure(GPIO_PF1_M1PWM5);
    GPIOPinConfigure(GPIO_PF0_M1PWM4);
    GPIOPinConfigure(GPIO_PE5_M1PWM3);

    GPIOPinTypePWM(GPIO_PORTE_BASE, GPIO_PIN_5);
    GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0); //M1PWM7
                                                                                        //配置 PWM1 Generator3·发生器

    PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    //配置 PWM1 Generator3 周期
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, 64000 - 1); // 20M/64k = 312.5Hz
    int fullScale = SysCtlClockGet() / (4.0f * freq) - 1;
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, fullScale);
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, fullScale);

    //配置 PWM1 Generator3 占空比
    // PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4 | PWM_OUT_5 | PWM_OUT_6 | PWM_OUT_7, 1000); //PWMGenPeriodGet(PWM1_BASE, PWM_GEN_3) * duty - 1);
    //使能 PWM1 输出
    PWMOutputState(PWM1_BASE, PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT | PWM_OUT_6_BIT | PWM_OUT_7_BIT, true);

    //使能 PWM1 发生器模块
    PWMGenEnable(PWM1_BASE, PWM_GEN_1);
    PWMGenEnable(PWM1_BASE, PWM_GEN_2);
    PWMGenEnable(PWM1_BASE, PWM_GEN_3);

    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_3, 4000);
    fullScale *= duty;
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4, fullScale);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5, fullScale);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6, fullScale);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7, fullScale);
    // LOCK F0
    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIO_PORTF_BASE + GPIO_O_CR) = 0x00;
    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0;
}

float f2(float a, float b, float c)
{
    //cout << "f2(" << a << "," << b << ")\n";
    li_outf("%f, %f, %f\n", a, b, c);
    return a + b + c;
}

void exp_test_hit()
{
    typedef float (*F2)(float a, int b);
    typedef uint32_t (*FI2)(uint32_t a, uint32_t b, uint32_t c);

    FI2 pf = (FI2)f2;
    float aai = 11, bbi = 22, cci = 33;
    uint32_t *aap, *bbp, *ccp;
    aap = (uint32_t *)(&aai);
    bbp = (uint32_t *)(&bbi);
    bbp = (uint32_t *)(&cci);
    uint32_t ddi = pf(to_voidf(aai), to_voidf(bbi), to_voidf(cci));
    float *ddp = (float *)(&ddi);
    li_outf("%f,%f\n", ddi, *ddp);
}

// set angle in deg
void seta(float ang)
{
    float maxd = 60;
    float sero_uo = 0.39 * 64000;             //10000-50000  0°-180° 222.22/°
    float sero_k = (float)40000 / (float)180; // u = sero_uo + deg*sero_k  222.22/°

    // int full = PWMGenPeriodGet(PWM1_BASE, PWM_GEN_1);
    // const float full = 80000000 / 312.5;
    limit_to(&ang, maxd);
    int u = ang * sero_k + sero_uo;
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_3, u);
}

int cmd_reg_set(int n, char *arg[])
{
    int regAdr = 0;
    if (n >= 2) // reg 0x1234
    {
        if (sscanf(arg[1], "%x", &regAdr) != 1)
        {
            li_error("bad arg", -185);
        }
    }
    if (n == 2)
    {
        int val = HWREG(regAdr);
        li_outf("%x\n", val);
        return 1;
    }
    if (n == 3)
    {
        int val;
        if (sscanf(arg[2], "%x", &val) != 1)
        {
            li_error("bad arg", -195);
        }
        HWREG(regAdr) = val;
        return 2;
    }
}

/*

VCC
GND
SCK/SPC
SDA/SDIO
SA0/SDO
CS
INT
FSY
*/